package com.demarc.pesquisas.negocio.service;

import java.io.Serializable;
import java.util.List;

import com.demarc.pesquisas.infraestrutura.excecao.NegocioException;
import com.demarc.pesquisas.infraestrutura.persistencia.Filtro;
import com.demarc.pesquisas.infraestrutura.persistencia.ObjetoPersistenteVersionado;
import com.demarc.pesquisas.infraestrutura.persistencia.ResultadoPaginado;

public interface IService<T extends ObjetoPersistenteVersionado<ID>, ID extends Serializable>
		extends Serializable {

	/**
	 * Insere um novo objeto.
	 * 
	 * @param entidade
	 *            objeto a ser inserido.
	 * 
	 * @return a chave do objeto recém inserido.
	 */
	void salvar(T entidade);

	/**
	 * Atualiza o objeto.
	 * 
	 * @param entidade
	 *            objeto a ser atualizado.
	 */
	void alterar(T entidade);

	/**
	 * Insere ou atualiza um novo objeto.
	 * 
	 * @param entidade
	 *            objeto a ser inserido.
	 * 
	 * @return a chave do objeto recém inserido ou alterado.
	 */
	void salvarOuAlterar(T entidade);

	/**
	 * Atualiza o onjeto fazendo o merge
	 * 
	 * @param entidade
	 */
	void merge(T entidade);

	/**
	 * Remove um objeto.
	 * 
	 * @param entidade
	 *            objeto a ser removido.
	 */
	void excluir(T entidade);

	/**
	 * Consulta um determinado objeto pela sua chave.
	 * 
	 * @param key
	 *            chave do objeto na tabela.
	 * @return retorna o objeto correspondente a chave, senão existir, retorna
	 *         nulo.
	 */
	T buscarPor(ID id);

	/**
	 * Consulta o maior valor de um determinado campo de uma tabela de acordo
	 * com os filtros infomados
	 * 
	 * @param property
	 * @param filtro
	 */
	<E> E buscarMaiorValor(String property, Filtro filtro);

	/**
	 * Realiza uma consulta que é filtrada apenas por um campo.
	 * 
	 * @param nomeCampo
	 *            nome do campo a ser filtrado.
	 * @param valorCampo
	 *            valor do campo a ser filtrado.
	 * @param atributosEOrdem
	 *            ordenação dos resultados.Ex: atributo:ordem -> id:asc
	 * @return uma lista com os resultados da consulta.
	 */
	List<T> consultarPorCampo(String nomeCampo, Object valorCampo,
			String... atributosEOrdem);

	/**
	 * Realiza a consulta por filtro, ordenando e paginando.
	 * 
	 * @param filtro
	 *            Filtro utilizado na consulta.
	 */
	ResultadoPaginado<T> consultarPaginandoPorFiltro(Filtro filtro);

	/**
	 * Consulta todos os objetos de uma determinada tabela agrupados pela
	 * propriedade passada como parâmetro.
	 * 
	 * @param property
	 *            propriedade a ser agrupada.
	 * 
	 * @return uma lista com todos os objetos da tabela.
	 */
	<E> List<E> listarPor(String property);

	/**
	 * Consulta todos os objetos de uma determinada tabela.
	 * 
	 * @param atributosEOrdem
	 *            ordenação dos resultados.Ex: atributo:ordem -> id:asc
	 * 
	 * @return uma lista com todos os objetos da tabela.
	 */
	List<T> listarOrdenadoPor(String... atributosEOrdem);

	/**
	 * Consulta um objeto pela sua chave.
	 * 
	 * @param id
	 *            chave do objeto a ser consultada.
	 * @return um objeto se existir, ou nulo.
	 */
	boolean existe(ID id);

	/**
	 * Validação realizada antes da inclusão.
	 * 
	 * @param obj
	 *            Objeto a ser validado.
	 * @throws NegocioException
	 *             Caso alguma validação falhe.
	 */
	void validarInclusao(T obj);

	/**
	 * Validação realizada antes da alteração.
	 * 
	 * @param obj
	 *            Objeto a ser validado.
	 * @throws NegocioException
	 *             Caso alguma validação falhe.
	 */
	void validarAlteracao(T obj);

	/**
	 * Validação realizada antes da inclusão ou alteração.
	 * 
	 * @param obj
	 *            Objeto a ser validado.
	 * @throws NegocioException
	 *             Caso alguma validação falhe.
	 */
	void validarInclusaoOuAlteracao(T obj);

	/**
	 * Validação realizada antes da exclusão.
	 * 
	 * @param obj
	 *            Objeto a ser validado.
	 * @throws NegocioException
	 *             Caso alguma validação falhe.
	 */
	void validarExclusao(T obj);

	/**
	 * Valida se o objeto passado com parâmetro é null ou vazio e lança a
	 * exceção com a mensagem de erro e os parâmetros passados.
	 * 
	 * @param objeto
	 *            Objeto a ser validado.
	 * @param msgErro
	 *            Mensagem de erro a ser lançada.
	 * @param parametros
	 *            Parâmetros a serem configurados na mensagem de erro.
	 */
	void validarObjetotNuloOuVazio(Object objeto, String msgErro,
			String... parametros);
}
